package org.chaiyi.template.core.framework.glob_handler;

import org.chaiyi.template.core.common.exception.BusinessError;
import org.chaiyi.template.core.common.exception.BusinessErrorType;
import org.springframework.core.annotation.Order;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebExceptionHandler;
import reactor.core.publisher.Mono;

import java.nio.charset.StandardCharsets;

@Order(-2)
@Component
public class ExceptionHandler implements WebExceptionHandler {
    @Override
    public Mono<Void> handle(ServerWebExchange exchange, Throwable ex) {
        if (ex instanceof BusinessError be) {
            return handleBusinessError(exchange, be);
        } else {
            return handleOtherError(exchange, ex);
        }
    }

    private Mono<Void> handleBusinessError(ServerWebExchange exchange, BusinessError be) {

        ServerHttpResponse response = exchange.getResponse();
        response.setStatusCode(HttpStatus.OK);
        response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
        DataBuffer dataBuffer = response.bufferFactory()
                .wrap(be.toJson().getBytes(StandardCharsets.UTF_8));
        return response.writeAndFlushWith(Mono.just(Mono.just(dataBuffer)));
    }

    private Mono<Void> handleOtherError(ServerWebExchange exchange, Throwable ex) {
        ServerHttpResponse response = exchange.getResponse();
        response.setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR);
        response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
        DataBuffer dataBuffer = response.bufferFactory()
                .wrap(new BusinessError("500", ex.getMessage()).level(BusinessErrorType.SEVERE).toJson().getBytes(StandardCharsets.UTF_8));
        return response.writeAndFlushWith(Mono.just(Mono.just(dataBuffer)));
    }

}
